﻿using MCPlatform.Models;
using MCPlatform.MotionLib.Base.AssitantClass;
using MCPlatform.MotionLib.Base.Environment;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace MCPlatform.Components.Utilities
{
    public static class Utility
    {
        /// <summary>
        /// 映射字典值到对象属性
        /// </summary>
        /// <typeparam name="T">类类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="dictionary">字典</param>
        public static void PopulateFromDictionary<T>(this T obj, Dictionary<string, string> dictionary) where T : class
        {
            foreach (var kvp in dictionary)
            {
                // 获取对象的属性信息
                PropertyInfo? property = obj.GetType().GetProperty(kvp.Key, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                if (property != null && property.CanWrite)
                {
                    // 获取属性类型
                    Type propertyType = property.PropertyType;
                    // 将字典值转换为属性类型
                    object value = Convert.ChangeType(kvp.Value, propertyType);
                    // 设置属性值
                    property.SetValue(obj, value);
                }
            }
        }

        /// <summary>
        /// 保存对象到文件
        /// </summary>
        /// <typeparam name="T">类类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="filePath">保存路径</param>
        /// <param name="title">第一行的抬头内容</param>
        /// <param name="endNewLine">使用结束换行，默认换</param>
        /// <param name="append">如果路径有文件内容，是否添加至最后，默认添加</param>
        public static void SaveToFile<T>(this T obj,string filePath,string title,bool endNewLine = true,bool append = true ) where T : class
        {
            // 获取对象的类型
            Type type = typeof(T);
            // 获取对象的属性
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            using (StreamWriter writer = new StreamWriter(filePath, append)) // 设置为 false，表示清空文件内容并写入新内容
            {
                writer.WriteLine($"{title}");
                foreach (PropertyInfo property in properties)
                {
                    // 获取属性的 DisplayNameAttribute 特性
                    var displayNameAttribute = property.GetCustomAttribute<DisplayNameAttribute>();
                    // 获取属性的 DisplayAttribute 特性
                    string? propertyName = displayNameAttribute != null ? displayNameAttribute.DisplayName : property.Name;
                    // 获取属性的值
                    object? value = property.GetValue(obj);
                    // 写入文件
                    writer.WriteLine($"{propertyName}: {GetNumberFromTextToString(value?.ToString())}");
                }

                if (endNewLine)
                {
                    writer.WriteLine();
                }
                
            }
        }

        /// <summary>
        /// 保存数据至文件路径
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="filePath"></param>
        /// <param name="title"></param>
        /// <param name="endNewLine"></param>
        /// <param name="append"></param>
        public static void SaveTableToFile(DataTable dt, string filePath, string title, bool endNewLine = true, bool append = true) 
        {

            if (dt.Rows.Count < 1)
            {
                return;
            }
            using (StreamWriter writer = new StreamWriter(filePath, append)) // 设置为 false，表示清空文件内容并写入新内容
            {
                writer.WriteLine($"{title}");
                foreach (DataRow row in dt.Rows)
                {
                    // 获取第二列和第三列的内容，并写入到文件中
                    string? column2Value = row[1].ToString(); // 第二列的内容
                    string? column3Value = row[2].ToString(); // 第三列的内容

                    writer.WriteLine($"{column2Value}\t{column3Value}");
                }

                if (endNewLine)
                {
                    writer.WriteLine();
                }

            }
        }

        /// <summary>
        /// 把字符串中的数字提取出来，转换为float
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>浮点数值</returns>
        public static float? GetNumberFromTextToFloat(string input)
        {
            string pattern = @"[-+]?\d+(\.\d+)?";

            // 创建正则表达式对象
            Regex regex = new Regex(pattern);

            // 在输入字符串中找到所有匹配项
            MatchCollection matches = regex.Matches(input);

            bool res = float.TryParse(matches[0].Value, out float result);

            if (!res)
            {
                return null;
            }

            return result;

        }

        /// <summary>
        /// 把字符串中的数字提取出来，转换为字符串
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>字符串值</returns>
        public static string? GetNumberFromTextToString(string? input)
        {
            if (input is null)
            {
                return null;
            }

            string pattern = @"[-+]?\d+(\.\d+)?";

            // 创建正则表达式对象
            Regex regex = new Regex(pattern);

            // 在输入字符串中找到所有匹配项
            MatchCollection matches = regex.Matches(input);

            return matches[0].Value.ToString();

            

        }


        /// <summary>
        /// 把字符串中的数字提取出来，转换为int
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>整形int</returns>

        public static int? GetNumberFromTextToInt(string? input)
        {
            if (input is null)
            {
                return null;
            }

            string pattern = @"[-+]?\d+(\.\d+)?";

            // 创建正则表达式对象
            Regex regex = new Regex(pattern);

            // 在输入字符串中找到所有匹配项
            MatchCollection matches = regex.Matches(input);

            bool res = int.TryParse(matches[0].Value, out int result);

            if (!res)
            {
                return null;
            }

            return result;

        }

        public static float ByteArrayToFloat(byte[] bytes)
        {
            Array.Reverse(bytes);
            // 如果需要转换为大端字节顺序  
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(bytes); // 反转四个字节的顺序  
            }


            // 现在字节数组以大端字节顺序存储，或者如果系统本身是大端的，则无需更改  
            return BitConverter.ToSingle(bytes, 0);
        }


        public static void WritePropertiesToFile(object obj, string filePath)
        {
            // Clear the file content if it already exists
            File.WriteAllText(filePath, string.Empty);

            using (StreamWriter writer = new StreamWriter(filePath))
            {
                Type type = obj.GetType();
                PropertyInfo[] properties = type.GetProperties();

                foreach (var property in properties)
                {
                    // Check if the property has the WriteToFile attribute
                    if (Attribute.IsDefined(property, typeof(WriteToFileAttribute)))
                    {
                        string name = property.Name;
                        var value = property.GetValue(obj);
                        writer.WriteLine($"{name}: {value}");
                    }
                }
            }
        }



        public static void ReadPropertiesFromFile(object obj, string filePath)
        {
            var type = obj.GetType();
            var properties = type.GetProperties();

            var lines = File.ReadAllLines(filePath);
            foreach (var line in lines)
            {
                var parts = line.Split(new[] { ':' }, 2);
                if (parts.Length != 2) continue;

                var name = parts[0].Trim();
                var value = parts[1].Trim();

                foreach (var property in properties)
                {
                    if (property.Name == name && Attribute.IsDefined(property, typeof(WriteToFileAttribute)))
                    {
                        // Convert the string value to the property type and set the value
                        if (property.PropertyType == typeof(int))
                        {
                            property.SetValue(obj, int.Parse(value));
                        }
                        else if (property.PropertyType == typeof(string))
                        {
                            property.SetValue(obj, value);
                        }
                        else if (property.PropertyType == typeof(bool))
                        {
                            bool val = value == "True" ? true : false;
                            property.SetValue(obj, val);
                        }
                        // Add more type conversions as needed
                        break;
                    }
                }
            }
        }



        /// <summary>
        /// 设置全部为未选中状态
        /// </summary>
        private static void SetAllProductUnselected(ObservableCollection<ProductModel> productModels)
        {
            if (productModels.Count > 0)
            {
                foreach (var product in productModels)
                {
                    product.IsLastSelected = false;
                }
            }
        }

        public static void SaveProducts(ObservableCollection<ProductModel> productModels)
        {
            if (productModels.Count > 0)
            {
                SaveConfigData.SaveConfig<ProductModel>(Paths.ProductConfigPaths, productModels.ToArray());

            }
        }


        /// <summary>
        /// 设置全部为未选中状态
        /// </summary>
        private static void SetAllProductUnselected(ref ObservableCollection<ProductModel> productModels)
        {
            if (productModels.Count > 0)
            {
                foreach (var product in productModels)
                {
                    product.IsLastSelected = false;
                }
            }
        }





        /// <summary>
        /// 坐标转换
        /// </summary>
        /// <param name="x1">视觉X坐标</param>
        /// <param name="y1">视觉Y坐标</param>
        /// <param name="angle">误差角度</param>
        /// <returns>刀头坐标</returns>
        public static (double x2, double y2) RotatePoint(double x1, double y1, double angle)
        {
            // 将角度转换为弧度
            double radians = angle * Math.PI / 180.0;

            // 计算旋转矩阵的元素
            double cosTheta = Math.Cos(radians);
            double sinTheta = Math.Sin(radians);

            // 应用旋转矩阵进行转换
            double x2 = x1 * cosTheta - y1 * sinTheta;
            double y2 = x1 * sinTheta + y1 * cosTheta;

            return (x2, y2);
        }


        /// <summary>
        /// 更新U轴角度
        /// </summary>
        /// <param name="prevX">上个X坐标</param>
        /// <param name="prevY">上个Y坐标</param>
        /// <param name="newX">目的X坐标</param>
        /// <param name="newY">目的Y坐标</param>
        /// <returns>U旋转角度相对值</returns>
        public static double UpdateUAngle(double prevX, double prevY, double newX, double newY)
        {

            // 计算运动方向
            double dx = newX - prevX;
            double dy = newY - prevY;

            if (Math.Abs(dx) < 0.1 && Math.Abs(dy) < 0.1)
            {
                return 0; // 如果没有移动，不需要调整角度
            }

            // 计算方向角度
            double theta = Math.Atan2(dy, dx); // 返回弧度
            double thetaDegrees = theta * (180.0 / Math.PI); // 转换为度数

            // 更新U轴角度           
            return thetaDegrees;

        }



        /// <summary>
        /// 计算U轴旋转角度绝对值
        /// </summary>
        /// <param name="originX"></param>
        /// <param name="originY"></param>
        /// <param name="newX"></param>
        /// <param name="newY"></param>
        /// <returns>U轴旋转的角度绝对值</returns>
        public static double CalculateAngle(double originX, double originY, double newX, double newY)
        {
            // 原点 (0, 0)
            //double originX = 0, originY = 0;

            // 计算运动方向
            double dx = newX - originX;
            double dy = newY - originY;

            // 计算方向角度
            double theta = Math.Atan2(dy, dx); // 返回弧度
            double thetaDegrees = theta * (180.0 / Math.PI); // 转换为度数

            return thetaDegrees; // 返回切割刀的旋转角度
        }


        /// <summary>
        /// 计算AB点，当A转了角度后B点新的坐标
        /// </summary>
        /// <param name="Ax">A点X轴坐标</param>
        /// <param name="Ay">B点Y轴坐标</param>
        /// <param name="Bx">B点X轴坐标</param>
        /// <param name="By">B点Y轴坐标</param>
        /// <param name="angleDegrees">A点旋转的角度</param>
        /// <returns>B旋转角度后的坐标</returns>
        public static (double, double) RotatePointB(double Ax, double Ay, double Bx, double By, double angleDegrees)
        {
            // 将角度转换为弧度
            double theta = angleDegrees * Math.PI / 180.0;

            // 计算新的A点坐标
            double A_prime_x = Ax * Math.Cos(theta) - Ay * Math.Sin(theta);
            double A_prime_y = Ax * Math.Sin(theta) + Ay * Math.Cos(theta);

            // 计算A到B的向量
            double Vx = Bx - Ax;
            double Vy = By - Ay;

            // 旋转向量
            double V_prime_x = Vx * Math.Cos(theta) - Vy * Math.Sin(theta);
            double V_prime_y = Vx * Math.Sin(theta) + Vy * Math.Cos(theta);

            // 计算新的B点坐标
            double B_prime_x = A_prime_x + V_prime_x;
            double B_prime_y = A_prime_y + V_prime_y;

            return (B_prime_x, B_prime_y);
        }



        /// <summary>
        /// 计算刀的旋转角度
        /// </summary>
        /// <param name="startPoint">起始点</param>
        /// <param name="midPoint">中间点</param>
        /// <param name="endPoint">结束点</param>
        /// <returns>开始角度，结束角度，移动角度</returns>
        public static (double, double, double) CalculateStartAngleAndEndAngle(Point startPoint, Point midPoint, Point endPoint)
        {
            var (center, radius) = CalculateCircleCenterAndRadius(startPoint, midPoint, endPoint);

            var startAngle = CalculateTangentAngle(startPoint, center);
            var endAngle = CalculateTangentAngle(endPoint, center);

            double disAngle = 0;

            if (IsClockwise(startPoint, midPoint, endPoint))
            {
                if (endAngle > 0)
                {
                    disAngle = endAngle - startAngle;
                }
                else
                {
                    disAngle = 360 + endAngle - startAngle;
                }


            }
            else
            {
                disAngle = endAngle - startAngle;
            }


            return (startAngle, endAngle, disAngle);


        }

        public static (Point, double) CalculateCircleCenterAndRadius(Point p1, Point p2, Point p3)
        {
            double ma = (p2.Y - p1.Y) / (p2.X - p1.X);
            double mb = (p3.Y - p2.Y) / (p3.X - p2.X);

            double centerX = (ma * mb * (p1.Y - p3.Y) + mb * (p1.X + p2.X) - ma * (p2.X + p3.X)) / (2 * (mb - ma));
            double centerY = -1 * (centerX - (p1.X + p2.X) / 2) / ma + (p1.Y + p2.Y) / 2;

            double radius = Math.Sqrt(Math.Pow(centerX - p1.X, 2) + Math.Pow(centerY - p1.Y, 2));

            return (new Point(centerX, centerY), radius);
        }

        public static double CalculateTangentAngle(Point current, Point center)
        {

            double dx = current.X - center.X;
            double dy = current.Y - center.Y;

            if (dx == 0 && dy == 0)
            {
                throw new ArgumentException("Point is the same as circle center.");
            }

            double slope = -dx / dy;

            if (dx == 0 && dy > 0)
            {
                return 0;
            }
            else if (dx == 0 && dy < 0)
            {
                return 180;
            }

            if (dy == 0 && dx > 0)
            {
                return 90;
            }
            else if (dy == 0 && dx < 0)
            {
                return -90;
            }


            return Math.Atan(slope) * (180 / Math.PI);


        }

        public static double AdjustCutterAngle(double angle)
        {
            // Convert angle to -180 to 180 range
            while (angle > 180)
            {
                angle -= 360;
            }
            while (angle < -180)
            {
                angle += 360;
            }

            return angle;
        }


        public static bool IsClockwise(Point A, Point B, Point C)
        {
            // Calculate vectors AB and BC
            double vectorAB_x = B.X - A.X;
            double vectorAB_y = B.Y - A.Y;
            double vectorBC_x = C.X - B.X;
            double vectorBC_y = C.Y - B.Y;

            // Calculate the cross product AB x BC
            double crossProduct = (vectorAB_x * vectorBC_y) - (vectorAB_y * vectorBC_x);

            // Determine the direction based on the sign of the cross product
            if (crossProduct > 0)
            {
                return false; // 逆时针
            }
            else if (crossProduct < 0)
            {
                return true; // 顺时针
            }
            else
            {
                return true;
                // This case would mean the points are collinear, which theoretically shouldn't happen on a circle
                //throw new Exception("Points are collinear, cannot determine arc direction.");
            }
        }






    }


    public struct Point
    {
        public double X { get; set; }
        public double Y { get; set; }

        public Point(double x, double y)
        {
            X = x;
            Y = y;
        }

        // 实现向量的减法  
        public static Point operator -(Point a, Point b)
        {
            return new Point(a.X - b.X, a.Y - b.Y);
        }

        // 实现向量的点积  
        public static double Dot(Point a, Point b)
        {
            return a.X * b.X + a.Y * b.Y;
        }

        // 计算向量的长度  
        public double Length()
        {
            return Math.Sqrt(X * X + Y * Y);
        }
    }
}
